package pers.fulsun.demo.springcloud.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.api.R;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.support.CronSequenceGenerator;
import org.springframework.web.bind.annotation.*;
import pers.fulsun.demo.springcloud.Constants;
import pers.fulsun.demo.springcloud.entity.SysSchedule;
import pers.fulsun.demo.springcloud.helper.CronTaskRegistrar;
import pers.fulsun.demo.springcloud.helper.SchedulingRunnable;
import pers.fulsun.demo.springcloud.service.SysScheduleService;
import pers.fulsun.demo.springcloud.utils.SpringUtil;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author fulsun
 * @since 2021-09-21
 */
@RestController
@AllArgsConstructor
@RequestMapping("/schedule")
public class SysScheduleController {
    /**
     * 定时任务操作类service
     */
    private SysScheduleService sysScheduleService;
    /**
     * 定时任务注册类
     */
    private CronTaskRegistrar cronTaskRegistrar;

    /**
     * 新增定时任务
     *
     * @param sysSchedule
     * @return
     */
    @PostMapping
    public String addJob(SysSchedule sysSchedule) {
        if (ObjectUtils.isNull(sysSchedule) || ObjectUtils.isNull(sysSchedule.getScheBeanName()) || ObjectUtils.isNull(sysSchedule.getScheMethod())) {
            return "请正确填写完整信息";
        }
        //判空
        if (ObjectUtils.isNotNull(sysSchedule.getScheBeanName())) {
            Object bean = SpringUtil.getBeanByName(sysSchedule.getScheBeanName());
            if (ObjectUtils.isNull(bean)) {
                return "查无此类，请核实";
            }
            try {
                bean.getClass().getDeclaredMethod(sysSchedule.getScheMethod());
            } catch (NoSuchMethodException e) {
                return "查无此方法，请核实";
            }
        }
        //验证cron表达式合法性
        if (ObjectUtils.isNull(sysSchedule.getScheCron()) || (!isValidExpression(sysSchedule.getScheCron()))) {
            return "请输入正确cron表达式";
        }
        //判重
        if (ObjectUtils.isNotNull(this.sysScheduleService.findByBeanNameAndMethod(sysSchedule.getScheBeanName(), sysSchedule.getScheMethod()))) {
            return "该定时任务已存在，请核实";
        }
        this.sysScheduleService.save(sysSchedule);
        //如果定时任务是激活状态
        if (sysSchedule.getScheStatus() == Constants.VALID) {
            SchedulingRunnable schedulingRunnable = new SchedulingRunnable(sysSchedule.getScheBeanName(), sysSchedule.getScheMethod());
            cronTaskRegistrar.addCronTask(schedulingRunnable, sysSchedule.getScheCron());
        }
        return "OK";
    }

    /**
     * 验证cron表达式是否正确
     *
     * @param corn
     * @return
     */
    public boolean isValidExpression(String corn) {
        //使用spring内置工具CronSequenceGenerator进行校验
        return CronSequenceGenerator.isValidExpression(corn);
    }

    /**
     * 更新定时任务操作类
     *
     * @param sysSchedule
     * @return
     */
    @PutMapping
    public String updateJob(SysSchedule sysSchedule) {
        if (ObjectUtils.isNull(sysSchedule) || ObjectUtils.isNull(sysSchedule.getScheBeanName()) || ObjectUtils.isNull(sysSchedule.getScheMethod())) {
            return "请正确填写完整信息";
        }
        if (ObjectUtils.isNull(sysSchedule.getId())) {
            return "请选择要修改的定时任务";
        }
        if (ObjectUtils.isNotNull(sysSchedule.getScheBeanName())) {
            Object bean = SpringUtil.getBeanByName(sysSchedule.getScheBeanName());
            if (ObjectUtils.isNull(bean)) {
                return "查无此类，请核实";
            }
            try {
                bean.getClass().getDeclaredMethod(sysSchedule.getScheMethod());
            } catch (NoSuchMethodException e) {
                return "查无此方法，请核实";
            }

            //验证cron表达式合法性
            if (ObjectUtils.isNull(sysSchedule.getScheCron()) || (!isValidExpression(sysSchedule.getScheCron()))) {
                return "请输入正确cron表达式";
            }

            SysSchedule oldSysSchedule = this.sysScheduleService.getById(sysSchedule.getId());
            this.sysScheduleService.updateById(sysSchedule);
            //停止之前的定时任务
            SchedulingRunnable schedulingRunnable = new SchedulingRunnable(oldSysSchedule.getScheBeanName(), oldSysSchedule.getScheMethod());
            this.cronTaskRegistrar.removeCronTask(schedulingRunnable);
            //判断是否重新启动
            if (sysSchedule.getScheStatus() == Constants.VALID) {
                cronTaskRegistrar.addCronTask(new SchedulingRunnable(sysSchedule.getScheBeanName(), sysSchedule.getScheMethod()), sysSchedule.getScheCron());
            }
        }
        return "OK";
    }

    /**
     * 删除定时任务
     * @param id
     * @return
     */
    @DeleteMapping("/{id}")
    public String removeJob(@PathVariable Integer id){
        //从数据库获取数据
        SysSchedule schedule = this.sysScheduleService.getById(id);
        if(ObjectUtils.isNull(schedule)){
            return "查无此数据，请核实";
        }
        //停止定时任务
        SchedulingRunnable schedulingRunnable = new SchedulingRunnable(schedule.getScheBeanName(), schedule.getScheMethod());
        this.cronTaskRegistrar.removeCronTask(schedulingRunnable);
        //最后删除数据库数据
        this.sysScheduleService.removeById(id);
        return "OK";
    }
    /**
     * 获取定时任务
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public SysSchedule getJob(@PathVariable Integer id){
        return this.sysScheduleService.getById(id);
    }
    /**
     * 获取定时任务列表
     * @param page
     * @param sysSchedule
     * @return
     */
    @GetMapping("/page")
    public IPage<SysSchedule> getPage(IPage<SysSchedule> page, SysSchedule sysSchedule){
        return this.sysScheduleService.page(page,new QueryWrapper<>(sysSchedule));
    }
}